package com.squirrel.common.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.squirrel.common.entity.Comment;
import com.squirrel.common.entity.User;
import com.squirrel.common.exception.BaseException;
import com.squirrel.common.mapper.CommentMapper;
import com.squirrel.common.mapper.UserMapper;
import com.squirrel.common.param.comment.CommentParam;
import com.squirrel.common.param.video.PageParam;
import com.squirrel.common.response.code.CodeEnum;
import com.squirrel.common.response.page.PageResult;
import com.squirrel.common.service.CommentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.squirrel.common.vo.comment.CommentVO;
import com.squirrel.common.vo.comment.CommentWithParentVO;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 *  CommentServiceImp 评论服务实现类
 * </p>
 *
 * @author 关远键
 * @since 2021/11/11 16:06
 */
@Service
public class CommentServiceImp extends ServiceImpl<CommentMapper, Comment> implements CommentService {

    @Value("${file.coming.path}")
    private String url;

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private UserMapper userMapper;

    /**
     * 获取视频的评论
     * 待改进
     * @author 关远键
     * @date 2021/11/23 15:30
     * @param videoId 视频ID
     * @param pageParam 分页
     * @return com.squirrel.common.response.page.PageResult<com.squirrel.common.vo.comment.CommentVO>
     */
    @Override
    public PageResult<CommentVO> getCommentByVideoId(Integer videoId, PageParam pageParam) {
        Page<Comment> page = new Page<>(pageParam.getNo(), pageParam.getSize());
        IPage<Comment> comments = commentMapper.getCommentByVideoId(page, videoId, -1);

        if (0 == comments.getTotal()) {
            throw new BaseException(CodeEnum.NON_RESOURCE);
        }

        ArrayList<CommentVO> list = new ArrayList<>();
        for (Comment comment : comments.getRecords()) {
            List<Comment> child = commentMapper.getByParentId(videoId, comment.getCommentId());

            if (0 == child.size()) {
                list.add(copyFromComment(comment));
            } else {
                CommentWithParentVO parentVO = new CommentWithParentVO();

                CommentVO vo = copyFromComment(comment);
                try {
                    BeanUtils.copyProperties(parentVO, vo);
                } catch (IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                    throw new BaseException(CodeEnum.FAIL);
                }

                ArrayList<CommentVO> parentChild = new ArrayList<>();
                for (Comment ch : child) {
                    parentChild.add(copyFromComment(ch));
                }
                parentVO.setChild(parentChild);

                list.add(parentVO);
            }

        }

        return new PageResult<>(list.size(), list);
    }

    /**
     * 用户视角的评论
     * @author 关远键
     * @date 2021/11/24 10:08
     * @param userId 用户ID
     * @param pageParam 分页
     * @return com.squirrel.common.response.page.PageResult<com.squirrel.common.vo.comment.CommentVO>
     */
    @Override
    public PageResult<CommentVO> getCommentByUserId(Integer userId, PageParam pageParam) {
        Page<Comment> voPage = new Page<>(pageParam.getNo(), pageParam.getSize());
        IPage<Comment> comments = commentMapper.getCommentByUserId(voPage, userId);

        if (0 == comments.getTotal()) {
            throw new BaseException(CodeEnum.NON_RESOURCE);
        }

        ArrayList<CommentVO> list = copyFromIPage(comments);
        return new PageResult<>(list.size(), list);
    }

    /**
     * 评论留言（仅支持一级和二级评论）
     * @author 关远键
     * @date 2021/11/24 9:30
     * @param commentParam
     * @return java.lang.Integer
     */
    @Override
    public Integer sendComment(CommentParam commentParam) {

        Comment selectById = commentMapper.selectById(commentParam.getCommentParentId());
        if (null != selectById && -1 != selectById.getCommentParentId()) {
            throw new BaseException(CodeEnum.PARAM_ERROR);
        }

        Comment comment = new Comment();

        try {
            BeanUtils.copyProperties(comment, commentParam);
        } catch (Exception e) {
            e.printStackTrace();
        }

        comment.setCommentTime(LocalDateTime.of(LocalDate.now(), LocalTime.now()));

        if (0 < commentMapper.insert(comment)) {
            return comment.getCommentId();
        }
        throw new BaseException(CodeEnum.DB_EXCEPTION);
    }

    /**
     * Comment ===> CommentVO
     * @author 关远键
     * @date 2021/11/23 22:09
     * @param comment
     * @return com.squirrel.common.vo.comment.CommentVO
     */
    private CommentVO copyFromComment(Comment comment) {
        User user = userMapper.selectById(comment.getUserId());

        CommentVO vo = new CommentVO();
        vo.setId(comment.getCommentId());
        vo.setUserId(comment.getUserId());
        vo.setAvatar(url + user.getAvatar());
        vo.setNickname(user.getNickname());
        vo.setContent(comment.getCommentContent());
        vo.setTime(comment.getCommentTime());

        return vo;
    }

    /**
     * 分页批量处理
     * @author 关远键
     * @date 2021/11/24 10:07
     * @param comments
     * @return java.util.ArrayList<com.squirrel.common.vo.comment.CommentVO>
     */
    private ArrayList<CommentVO> copyFromIPage(IPage<Comment> comments) {
        ArrayList<CommentVO> list = new ArrayList<>();
        for (Comment comment: comments.getRecords()) {
            CommentVO vo = copyFromComment(comment);
            if (vo instanceof CommentWithParentVO) {
                CommentWithParentVO withParentVO = (CommentWithParentVO) vo;
                list.add(withParentVO);
            } else {
                list.add(vo);
            }
        }
        return list;
    }


}
